// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_BROWSER_UI_UTIL_LABEL_LINK_CONTROLLER_H_
#define IOS_CHROME_BROWSER_UI_UTIL_LABEL_LINK_CONTROLLER_H_

#import <UIKit/UIKit.h>
#include "ios/chrome/browser/procedural_block_types.h"

class GURL;

// A LabelLinkController manages a UILabel instance that is to have tappable
// substrings ("links"). The controller handles styling the link areas (if
// desired), and installs a gesture recognizer on the label that will trigger if
// the specified regions are tapped. Multiple regions of the label may be
// defined as links, and they may trigger different actions.
// Each LabelLinkController calls a single action (a block that takes a GURL
// parameter) for all taps; different links are defined by having different
// URLs associated with them.
// The LabelLinkController observes (via KVO) changes in the label's size, style
// and text. If the label's bounds or style change, the controller recomputes
// the link areas. If the text changes, all of the defined links for the label
// are cleared (since they are presumed to be meaningless).
// To prevent spurious recomputation of link areas, it is best to apply any
// text manipulations and styling to the label before initializing a
// LabelLinkController with it.
@interface LabelLinkController : NSObject

// If |showTapAreas| is true in a debug build, the tappable regions of the label
// will have colored rectangles around them, with different colors for each URL,
// and a darker outline around the exact text that the tappable region is for.
// In non-debug builds, setting this property has no effect.
@property(nonatomic, assign) BOOL showTapAreas;

// Sets the link color for any defined links, updating the controlled label's
// attributed text accordingly.
@property(nonatomic, copy) UIColor* linkColor;

// Sets the link underline style for any defined links, updating the controlled
// label's attributed text accordingly.
@property(nonatomic, assign) NSUnderlineStyle linkUnderlineStyle;

// Sets the link font for any defined links, updating the controlled label's
// attributed text accordingly.
@property(nonatomic, strong) UIFont* linkFont;

// Creates a new controller for |label|, keeping a strong reference. |action| is
// the block called for any tapped link.
- (instancetype)initWithLabel:(UILabel*)label
                       action:(ProceduralBlockWithURL)action;

// Adds a link to the controlled label at |range| in the label's text, which
// will call the receiver's action block when tapped, passing in |url|.
// |accessibilityID| is set to the button over the link.
- (void)addLinkWithRange:(NSRange)range
                     url:(GURL)url
         accessibilityID:(NSString*)accessibilityID;

// Calls |[self addLinkWithRange:range url:url accessibilityID:nil]|.
- (void)addLinkWithRange:(NSRange)range url:(GURL)url;

@end

@interface LabelLinkController (Testing)

// Testing interface for LabelLinkController.

// This is the class that will be instantiated to do text mapping; by default
// it is CoreTextMapper, but tests can assign to this property to do dependency
// injection.
@property(nonatomic, assign) Class textMapperClass;
// Returns the tap rects generated by the controller that are associated with
// |url|.
- (NSArray*)tapRectsForURL:(GURL)url;
// Return all button frames.
- (NSArray*)buttonFrames;
// Simulates a tap in the controlled label at |point|. No touch events are
// generated, but |action| should be invoked if |point| is inside a tap rect.
- (void)tapLabelAtPoint:(CGPoint)point;

@end

#endif  // IOS_CHROME_BROWSER_UI_UTIL_LABEL_LINK_CONTROLLER_H_
